package model.item;

import java.util.ArrayList;
import java.util.Iterator;

import model.entity.Entity;

public class Inventory {

	private ArrayList<InventoryItem> inventoryList;
	private Weapon equippedWeapon;
	private Armor equippedArmor;
	private InventoryWeaponState inventoryWeaponState;
	private InventoryArmorState inventoryArmorState;
	private int maxSize;
	private int gold;
	private static final int goldcap=200000000;
	
	/**
	 * default constructor
	 * equipped items are set to defaults (most very basic weapon and armor)
	 * armor and weapon states start in default
	 * max inventory size is 7
	 * 
	 * gold and items must be added in after construction
	 */
	public Inventory(){
		inventoryList=new ArrayList<InventoryItem>();
		equippedWeapon=Weapon.getDefaultWeapon();
		equippedArmor=Armor.getDefaultArmor();
		inventoryWeaponState= new DefaultWeaponState();
		inventoryArmorState= new DefaultArmorState();
		maxSize=7;
		gold=0;
	}
	
	/**
	 * special constructor allow you to make your own inventory size
	 * @param inventorySize
	 */
	public Inventory(int inventorySize){
		inventoryList=new ArrayList<InventoryItem>();
		equippedWeapon=Weapon.getDefaultWeapon();
		equippedArmor=Armor.getDefaultArmor();
		inventoryWeaponState= new DefaultWeaponState();
		inventoryArmorState= new DefaultArmorState();
		maxSize=inventorySize;
		gold=0;
	}

	
	/**
	 * checks if there is room for item in inventory
	 * could be overriden to make use of item parameter if keeping track of mulitplicity.
	 * @param item
	 * @return
	 */
	public boolean canReceive(InventoryItem item){
		if(inventoryList.size()>=maxSize)return false;
		return true;
	}
	
	public boolean canAfford(int value){
		if(value>gold)return false;
		else return true;
	}
	
	public void addItem(InventoryItem item){
		inventoryList.add(item);
	}
	/**
	 * attempts to add an amount of gold to the inventory.
	 * if amount added would take gold in inventory over gold cap,
	 * addGold sets gold equal to gold cap.
	 * @param amount
	 */
	
	public void addGold(int amount){
		amount=amount+gold;
		if(amount>goldcap)amount=goldcap-gold;
		gold=amount+gold;
	}
	
	/**
	 * attempts to remove an amount of gold from inventory
	 * @param amount is the amount of gold requested to be removed from inventory
	 * @return change is the amount that is actually returned
	 * 			can be either 'amount' or the amount of gold in the inventory, which
	 * 			ever is less.
	 */
	public int removeGold(int amount){
		int newGold=gold-amount;
		if(newGold<0) newGold=0;
		int change=newGold-gold;
		gold=newGold;
		return change;
	}
	
	public int size() {
		return inventoryList.size();
	}

	public InventoryItem getItem(int index) {
		
		return inventoryList.get(index);
	}
	
	public void removeItem(InventoryItem item) {
		inventoryList.remove(item);
	}
	
	public Iterator<InventoryItem> getInventory() {
		return inventoryList.iterator();
	}
	public void equipWeapon(Entity entity, Weapon weapon) {
		inventoryWeaponState.equipWeapon(entity, weapon);
		
	}
	
	public void equipArmor(Entity entity, Armor armor) {
		inventoryArmorState.equipArmor(entity, armor);
	}
	
	public void unequipWeapon(Entity entity, Weapon weapon) {
		inventoryWeaponState.unequipWeapon(entity);
	}
	
	public void unequipArmor(Entity entity) {
		inventoryArmorState.unequipArmor(entity);
	}
	private interface InventoryWeaponState {
		public void equipWeapon(Entity entity, Weapon weapon);
		public void unequipWeapon(Entity entity); 
	}
	
	private interface InventoryArmorState {
		public void equipArmor(Entity entity, Armor armor);
		public void unequipArmor(Entity entity); 
	}
	
	private class DefaultWeaponState implements InventoryWeaponState {

		@Override
		public void equipWeapon(Entity entity, Weapon weapon) {
			entity.removeStatsPersistMods(equippedWeapon.getStatMods());
			entity.addStatsPersistMods(weapon.getStatMods());
			inventoryList.remove(weapon);
			equippedWeapon = weapon;
			inventoryWeaponState = new SpecialWeaponState();
			
		}

		@Override
		public void unequipWeapon(Entity entity) {
			return;
		}
		
	}
	
	private class SpecialWeaponState implements InventoryWeaponState {

		@Override
		public void equipWeapon(Entity entity, Weapon weapon) {
			entity.removeStatsPersistMods(equippedWeapon.getStatMods());
			inventoryList.add(equippedWeapon);
			entity.addStatsPersistMods(weapon.getStatMods());
			inventoryList.remove(weapon);
			equippedWeapon = weapon;
			inventoryWeaponState = this;
			
		}

		@Override
		public void unequipWeapon(Entity entity) {
			entity.removeStatsPersistMods(equippedWeapon.getStatMods());
			inventoryList.add(equippedWeapon);
			Weapon newDefaultWeapon = Weapon.getDefaultWeapon();
			entity.addStatsPersistMods(newDefaultWeapon.getStatMods());
			equippedWeapon = newDefaultWeapon;
			inventoryWeaponState = new DefaultWeaponState();
			
		}

	}
	private class DefaultArmorState implements InventoryArmorState {

		@Override
		public void equipArmor(Entity entity, Armor armor) {
			entity.removeStatsPersistMods(equippedArmor.getStatMods());
			entity.addStatsPersistMods(armor.getStatMods());
			inventoryList.remove(armor);
			equippedArmor = armor;
			inventoryArmorState = new SpecialArmorState();
			
		}

		@Override
		public void unequipArmor(Entity entity) {
			return;
			
		}

	}
	
	private class SpecialArmorState implements InventoryArmorState {

		@Override
		public void equipArmor(Entity entity, Armor armor) {
			entity.removeStatsPersistMods(equippedArmor.getStatMods());
			inventoryList.add(equippedArmor);
			entity.addStatsPersistMods(armor.getStatMods());
			inventoryList.remove(armor);
			equippedArmor = armor;
			inventoryArmorState = this;
			
		}

		@Override
		public void unequipArmor(Entity entity) {
			entity.removeStatsPersistMods(equippedArmor.getStatMods());
			inventoryList.add(equippedArmor);
			Armor newDefaultArmor = Armor.getDefaultArmor();
			entity.addStatsPersistMods(newDefaultArmor.getStatMods());
			equippedArmor = newDefaultArmor;
			inventoryArmorState = new DefaultArmorState();
			
		}
	}
}

